﻿using Acaweb.Data.Contracts;
using Acaweb.Model.Entities;
using Acaweb.Model.Entities.DatosCompuestos;
using Acaweb.Componentes.Contracts;
using System.Collections.Generic;
using System.Linq;
using System;

namespace Acaweb.Componentes
{
    public class CursosMatriculadosService : BaseService, ICursosMatriculadosService
    {
        private ICursosMatriculadosDao _CursosMatriculadosDao;
        private IHorariosCursosDao _HorariosCursosDao;
        private ICalendarioDao _CalendarioDao;
        private IHistorialCursosDao _HistorialCursosDao;
        private ICalendarioNotasDao _CalendarioNotasDao;

        public ICalendarioNotasDao CalendarioNotasDao
        {
            get { return _CalendarioNotasDao; }
            set { _CalendarioNotasDao = value; }
        }

        public IHistorialCursosDao HistorialCursosDao
        {
            get { return _HistorialCursosDao; }
            set { _HistorialCursosDao = value; }
        }

        public ICalendarioDao CalendarioDao
        {
            get { return _CalendarioDao; }
            set { _CalendarioDao = value; }
        }

        public IHorariosCursosDao HorariosCursosDao
        {
            get { return _HorariosCursosDao; }
            set { _HorariosCursosDao = value; }
        }

        public ICursosMatriculadosDao CursosMatriculadosDao
        {
            get { return _CursosMatriculadosDao; }
            set { _CursosMatriculadosDao = value; }
        }

        public CursosMatriculados GetById(CursosMatriculadosPk Curso)
        {
            return CursosMatriculadosDao.GetById(Curso);
        }

        public IList<CursosMatriculados> GetByCurso(CursoPk Curso)
        {
            return CursosMatriculadosDao.GetByCurso(Curso);
        }

        public IList<CursosMatriculados> GetByEstudiante(int Estudiante)
        {
            return CursosMatriculadosDao.GetByEstudiante(Estudiante);
        }

        public int CorteHabilitado(CursoPk Curso)
        {
            int Corte = 0;

            List<CalendarioNotas> Calendario = CalendarioNotasDao.GetByCurso(Curso).ToList();

            foreach (CalendarioNotas CN in Calendario)
            {
                if (CN.Habilitada())
                    Corte = CN.CalendarioNotasPk.Corte;
            }

            return Corte;
        }

        public void Evaluar(CursosMatriculadosPk CursoMatriculado, double Nota, string CodigoDocente)
        {
            IList<HorariosCursos> Horarios = HorariosCursosDao.GetByCurso(CursoMatriculado.CursoPk, CodigoDocente);

            if (Horarios.Count > 0)
            {
                CursosMatriculados MyCurso = CursosMatriculadosDao.GetById(CursoMatriculado);

                int Corte = CorteHabilitado(MyCurso.CursoMatriculadoPk.CursoPk);

                if (Corte != 0)
                {
                    switch (Corte)
                    {
                        case 1:
                            MyCurso.Nota1 = Nota;
                            break;
                        case 2:
                            MyCurso.Nota2 = Nota;
                            break;
                        case 3:
                            MyCurso.Nota3 = Nota;
                            break;
                        case 4:
                            MyCurso.Nota4 = Nota;
                            break;
                        case 5:
                            MyCurso.Nota5 = Nota;
                            break;
                    }

                    CursosMatriculadosDao.Update(MyCurso);
                }
            }
        }

        public void CreateCursosMatriculados(CursosMatriculados CursoMatriculado)
        {
            CursoMatriculado.CursoMatriculadoPk.CursoPk.PerdiodoAcademico = CalendarioDao.getByEstado(EstadoPeriodo.A).First().PeridoAcademico;

            List<CursosMatriculados> Cursos = GetByEstudiante(CursoMatriculado.CursoMatriculadoPk.CodigoEstudiante, CursoMatriculado.CursoMatriculadoPk.CursoPk.PerdiodoAcademico).ToList();

            if (Cursos.Count == 0)
            {
                CursosMatriculadosDao.Save(CursoMatriculado);
            }
            else
            {
                Cursos = DeepLoad(Cursos).ToList();
                if (IsNotTimeConffict(CursoMatriculado.Curso, Cursos))
                {
                    CursosMatriculadosDao.Save(CursoMatriculado);
                }
                else
                {
                    throw new Exception("Conficto de horarios");
                }

            }
        }

        private bool IsNotTimeConffict(Cursos Curso, List<CursosMatriculados> CursosMatriculados)
        {
            List<HorariosCursos> HorariosOcupados = new List<HorariosCursos>();
            CursosMatriculados.ForEach(t=>HorariosOcupados.AddRange(t.Curso.ListaHorariosCursos));

            foreach (HorariosCursos Horario in Curso.ListaHorariosCursos)
            {
                List<HorariosCursos> DayOfWeek = HorariosOcupados.FindAll(t => t.HorarioCursoPk.Dia == Horario.HorarioCursoPk.Dia && t.HorarioCursoPk.TipoHorario == Horario.HorarioCursoPk.TipoHorario);
                if (DayOfWeek.Count > 0)
                    return false;
            }
            return true;
        }

        public bool IsNotTimeConfflict(List<CursosMatriculados> CursosMatriculados)
        {

            foreach (CursosMatriculados Curso in CursosMatriculados)
            {
                bool Rta = IsNotTimeConffict(Curso.Curso, CursosMatriculados.FindAll(t => t != Curso));
                if (!Rta)
                    return false;
            }

            return true;
        }

        public IList<CursosMatriculados> GetByEstudiante(int Estudiante, PeriodoAcademico PeriodoAcademico)
        {
            return DeepLoad(CursosMatriculadosDao.GetByEstudiante(Estudiante, PeriodoAcademico));
        }

        public static bool IsAproved(Model.Entities.CursosMatriculados CursoMatriculado)
        {
            return CursoMatriculado.NotaDefinitiva >= CursoMatriculado.Curso.NotaMinAprovatoria || CursoMatriculado.NotaValidacion >= CursoMatriculado.Curso.NotaMinAprovatoria;
        }

        public IList<CursosMatriculados> GetCursosMatriculadosAprovados(int CodigoEstudiante)
        {
            List<HistorialCursos> Historial = HistorialCursosDao.GetByEstudiante(CodigoEstudiante).Where(t => t.NotaDefinitiva > 3).ToList();

            List<CursosMatriculados> Cursos = new List<CursosMatriculados>();

            Historial.ForEach(t=>Cursos.Add(t.ToCursoMatriculado()));

            return Cursos;
        }

        private IList<CursosMatriculados> DeepLoad(IList<CursosMatriculados> Lista)
        {
            Lista.ToList().ForEach(t => t.Curso.ListaHorariosCursos = _HorariosCursosDao.GetByCurso(t.CursoMatriculadoPk.CursoPk).ToList());

            return Lista;
        }


    }
}
